﻿#include "dynamicmapshowwindow.h"
#include "viewobject.h"
#include "dynamicmap.h"
#include <QDebug>
#include <QList>

int interval_unequal_offset = 0;
int all_unequal_offset = 0;

DynamicMapShowWindow::DynamicMapShowWindow(QString xml_path, QString img_path, QWidget *parent)
    : QWidget(parent)
    , m_xml_path(xml_path)
    , m_img_path(img_path)
    , m_setmask_flag(false)
    , m_python_data(NULL)
{
    setWindowFlags(Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint);
    setFocusPolicy(Qt::NoFocus);

    m_current_station_pos = -1;
    m_interval_station_num = 0;
    m_all_station_num = 0;
    mViewObjectVector.clear();
    m_shown_acrossxml_objs.clear();
    m_new_acrossxml_objs.clear();
    m_shown_objs.clear();
    m_new_objs.clear();
}

DynamicMapShowWindow::~DynamicMapShowWindow()
{
    destroy_all_child();
}

void DynamicMapShowWindow::set_show_data(QString file, ProtocolData *python_data, QString xml_path, QString img_path)
{
    m_file_name = file;
    m_python_data = python_data;
    m_xml_path = xml_path;
    m_img_path = img_path;

    //存储新的跨越xml控件
    m_new_acrossxml_objs.clear();
    m_new_objs.clear();
    xml_to_vector(m_xml_path + m_file_name);

    //遍历老的跨越xml控件
    auto it = m_shown_acrossxml_objs.begin();
    while (it != m_shown_acrossxml_objs.end())
    {
        //新的里面没有老的，就把老的删除
        if (!m_new_acrossxml_objs.contains(*it))
        {
            destroy_child_by_name(*it);
            it = m_shown_acrossxml_objs.erase(it);
        } else
        {
            ++it;
        }
    }
}

void DynamicMapShowWindow::destroy_child_by_name(QString name)
{
    auto it = mViewObjectVector.begin();
    while (it != mViewObjectVector.end())
    {
        //删除结构体中的对象
        if ((*it)->object->GetObjectParam()->GetName() == name)
        {
            (*it)->object->hide();
            delete (*it)->object;
            (*it)->object = NULL;

            //删除结构体对象
            delete (*it);
            (*it) = NULL;

            it = mViewObjectVector.erase(it);
        } else
        {
            ++it;
        }
    }
}

void DynamicMapShowWindow::destroy_all_child()
{
    auto it = mViewObjectVector.begin();
    while (it != mViewObjectVector.end())
    {
        //删除结构体中的对象
        if ((*it) != NULL && (*it)->object != NULL)
        {
            (*it)->object->hide();
            delete (*it)->object;
            (*it)->object = NULL;

            //删除结构体对象
            delete (*it);
            (*it) = NULL;

            it = mViewObjectVector.erase(it);
        } else
        {
            ++it;
        }
    }
}

//只是把所有控件都隐藏,除了跨越xml滚动条
void DynamicMapShowWindow::hide_all_child()
{
    auto it = mViewObjectVector.begin();
    while (it != mViewObjectVector.end())
    {
        if (!(*it)->object->GetObjectParam()->GetName().contains("acrossxml"))
            (*it)->object->hide();

        it++;
    }
}

void DynamicMapShowWindow::dymap_show_window_setmask(ViewObjectInfo *info, QMap<QString, change_property> items_change)
{
    QString obj_name = info->object->GetObjectParam()->GetObjectName();
    ParamObject *pobject = info->object->GetObjectParam();
    if (ZERO != obj_name.compare("SubtractView"))
         return;

    bool change = false;
    int  change_x = 0;
    int  change_y = 0;
    int  change_w = 0;
    int  change_h = 0;

    if (m_python_data != NULL)
    {
        if (items_change.size() != 0)
        {
            for (auto it = items_change.begin(); it != items_change.end(); it++)
            {
                if (!it.key().compare(pobject->GetName()))
                {
                    change = true;
                    if (it.value().x != DEFAULTVAL)
                        change_x = it.value().x;
                    else
                        change_x = pobject->GetX();
                    if (it.value().y != DEFAULTVAL)
                        change_y = it.value().y;
                    else
                        change_y = pobject->GetY();
                    if (it.value().w != DEFAULTVAL)
                        change_w = it.value().w;
                    else
                        change_w = pobject->GetWidth();
                    if (it.value().h != DEFAULTVAL)
                        change_h = it.value().h;
                    else
                        change_h = pobject->GetHeight();
                    if (it.value().content == "hide")
                    {
                        m_setmask_flag = false;
                        return;
                    }
                }
            }
        }
    }

    if (change)
        m_sub_rect = QRect(change_x - change_w/2, change_y - change_h/2, change_w, change_h);
    else
        m_sub_rect = QRect(pobject->GetX() - pobject->GetWidth()/2,
                           pobject->GetY() - pobject->GetHeight()/2,
                           pobject->GetWidth(), pobject->GetHeight());

    m_setmask_flag = true;
    win32_setmask(m_sub_rect);
}

void DynamicMapShowWindow::win32_setmask(QRect sub_rect)
{
#ifdef __WIN32__
    //只在windows下使用，只生效最后一次setmask
    QRegion subtract_region = QRegion(sub_rect);
    QRegion fullRegion(rect());
    setMask(fullRegion.subtracted(subtract_region));
    LOG_QDEBUG << "subtract_region: " << subtract_region;
#endif
}

void DynamicMapShowWindow::show_by_index(ProtocolData *ptr)
{
    QList<int> index_list;
    foreach (ViewObjectInfo *info, mViewObjectVector)
    {
        if (!index_list.contains(info->object->GetObjectParam()->GetIndex()))
            index_list.append(info->object->GetObjectParam()->GetIndex());
    }

    std::sort(index_list.begin(), index_list.end());

    LOG_QDEBUG << "\n\n=========================================show pictures============================================";
    LOG_QDEBUG << "prefix:" << m_img_path;

    foreach (int index, index_list)
    {
        foreach (ViewObjectInfo *info, mViewObjectVector)
        {
            if (info->object->GetObjectParam()->GetIndex() == index)
            {
                //只有新来的或者老的acrossxml才能重新显示
                if (m_new_objs.contains(info->unique_name) || info->object->GetObjectParam()->GetName().contains("acrossxml"))
                {
                    info->object->setParent(this);
                    info->object->SetFilename(m_file_name);
                    info->object->SetProtocolData(ptr);
                    info->object->SetResPathPrefix(m_img_path);
                    info->object->ShowObject();
                    qDebug() << "";
                }
                //setmask
                if (m_python_data)
                    dymap_show_window_setmask(info, m_python_data->items_change);
                else
                    win32_setmask(info->object->geometry());
            }
        }
    }
    //保证hqv最后显示,ShowObject只显示第一帧
    foreach (ViewObjectInfo *info, mViewObjectVector)
        info->object->StartHqv();
}

void DynamicMapShowWindow::diff_show_suffix(QString suffix)
{
    foreach (ViewObjectInfo *info, mViewObjectVector)
    {
        QString obj_name = info->object->GetObjectParam()->GetObjectName();
        if (obj_name != "TrainView" && obj_name != "EtaView" &&
            obj_name != "SubtractView" && obj_name != "TimeView")
        {
            //上述subtract eta time不需要加后缀切换语言，train还未实现，也可实现,需要重写，它有两张图
            info->object->AddSuffixAndReloadPic(suffix);
        }
    }
}

void DynamicMapShowWindow::diff_show_itemschange(QMap<QString, change_property> items_change)
{
    //每个控件都跑，找到新的图才正在换图
    foreach (ViewObjectInfo *info, mViewObjectVector)
    {
        QString obj_name = info->object->GetObjectParam()->GetObjectName();
        if (obj_name != "SubtractView")
        {
            info->object->ReRunItemsChangeAndShow(items_change);
        } else
        {
            dymap_show_window_setmask(info, items_change);
        }
    }
}

void DynamicMapShowWindow::diff_show_object(DiffShowType dfstype, ProtocolData *python_data)
{
    switch (dfstype)
    {
        case DiffShowSuffix:
            diff_show_suffix(python_data->suffix);
        break;

        case DiffShowItemsChange:
            diff_show_itemschange(python_data->items_change);
        break;

        default:
        break;
    }
}

void DynamicMapShowWindow::show_file(ProtocolData *ptr)
{
     if (m_file_name.contains("emergency")
            && m_python_data != NULL
            && m_python_data->emergency_img != "")
     {
         show();
         return;
     }

     if (ptr)
     {
        if (ZERO == ptr->ui_type.compare(IntervalFlag))
        {
            QList<int> point_pos_list;
            QList<int> name_pos_list;
            QList<int> line_pos_list;

            for (int i = 0; i < mViewObjectVector.size(); i++)
            {
                ViewObjectInfo *info = mViewObjectVector[i];
                if (ZERO == info->object->GetObjectParam()->GetObjectName().compare("PointView"))
                {
                    if (!point_pos_list.contains(info->object->GetObjectParam()->GetX()))
                        point_pos_list.append(info->object->GetObjectParam()->GetX());
                }
                else if (ZERO == info->object->GetObjectParam()->GetObjectName().compare("StationView"))
                {
                    if (!name_pos_list.contains(info->object->GetObjectParam()->GetX()))
                        name_pos_list.append(info->object->GetObjectParam()->GetX());
                }
                else if (ZERO == info->object->GetObjectParam()->GetObjectName().compare("LineView"))
                {
                    if (!line_pos_list.contains(info->object->GetObjectParam()->GetX()))
                        line_pos_list.append(info->object->GetObjectParam()->GetX());
                }
            }

            std::sort(point_pos_list.begin(), point_pos_list.end());//排序
            std::sort(name_pos_list.begin(), name_pos_list.end());//排序
            std::sort(line_pos_list.begin(), line_pos_list.end());//排序

            int start_id = ptr->start_id;
            int stop_id = ptr->stop_id;
            int rundir = RUN_INVALID;
            int current = m_current_station_pos;
            int count = m_interval_station_num;

            int curr_id = ptr->curr_or_next_id;
            LOG_QDEBUG << "-------interval--------"
                       << "start_id:" << start_id
                       << "stop_id:" << ptr->stop_id
                       << "curr_id:" << curr_id
                       << "current:" << current
                       << "count:" << count
                       << "all_station_num:" << m_all_station_num;

            int tmp = -1;

            bool is_mirror = false;

            if (ptr->file_path.contains("mirror"))
                is_mirror = true;

            if (start_id < stop_id)
                rundir = RUN_UP;
            else if (start_id > stop_id)
                rundir = RUN_DOWN;

            /*
               若交路后剩下的站点个数小于区间图站点个数，那么start_id和stop_id就需要扩展了，扩展规则需要定
               或者在计算头部和尾部的时候直接使用1和28(总站点数)去计算，交路的当前站除了1,2和27,28其余都在中间
            */

            int interval_start = start_id;
            int interval_stop  = stop_id;
            if (m_all_station_num != 0)
            {
                if(rundir == RUN_UP)
                {
                    interval_start = 1;
                    interval_stop  = m_all_station_num;
                }
                else if(rundir == RUN_DOWN)
                {
                    interval_start = m_all_station_num;
                    interval_stop  = 1;
                }
            }

            if (rundir == RUN_UP)
            {
                //计算位置在头上
                if ((curr_id - interval_start) < current)
                    current = curr_id - interval_start + 1;

                //计算位置在尾部
                if (interval_stop - curr_id < count - current)
                    current = count - (interval_stop - curr_id);

                tmp = curr_id - current;
                LOG_QDEBUG << "up ===" << "curr_id:" << curr_id << "current:" << current;
            }
            else if (rundir == RUN_DOWN)
            {
                if (interval_start - curr_id < current)
                   current =  interval_start - curr_id + 1;

                if ((curr_id - interval_stop) < count - current)
                    current = count - (curr_id - interval_stop);

                LOG_QDEBUG << "down ===" << "curr_id:" << curr_id << "current:" << current;

                tmp = curr_id + current;

            }
            LOG_QDEBUG << "interval_tmp" << tmp;

            for (int i = 0; i < mViewObjectVector.size(); i++)
            {
                if (ZERO != mViewObjectVector[i]->object->GetObjectParam()->GetObjectName().compare("StationView") &&
                        ZERO != mViewObjectVector[i]->object->GetObjectParam()->GetObjectName().compare("LineView") &&
                        ZERO != mViewObjectVector[i]->object->GetObjectParam()->GetObjectName().compare("PointView"))
                    continue;
                for (int j = 0; j < point_pos_list.size(); j++)
                {
                    if (ZERO == mViewObjectVector[i]->object->GetObjectParam()->GetObjectName().compare("PointView") &&
                        mViewObjectVector[i]->object->GetObjectParam()->GetX() == point_pos_list.at(j))
                    {

                       if (rundir == RUN_UP)
                       {
                           if (is_mirror)
                           {
                               mViewObjectVector[i]->object->GetObjectParam()->SetStId(tmp + count - j);
                               LOG_QDEBUG << "interval up mirror stid" << tmp + count - j;
                           }
                           else
                           {
                               mViewObjectVector[i]->object->GetObjectParam()->SetStId(tmp + j + 1);
                               LOG_QDEBUG << "interval up stid" << tmp + j + 1;
                           }
                       }
                       else if (rundir == RUN_DOWN)
                       {
                           if (is_mirror)
                           {
                                mViewObjectVector[i]->object->GetObjectParam()->SetStId(tmp - count + j);
                                LOG_QDEBUG << "interval down mirror stid:" << tmp - count + j;
                           }
                           else
                           {
                               mViewObjectVector[i]->object->GetObjectParam()->SetStId(tmp - j - 1);
                               LOG_QDEBUG << "interval down stid" << tmp - j - 1;
                           }
                       }
                       mViewObjectVector[i]->object->GetObjectParam()->SetName(QString("point%1").arg(mViewObjectVector[i]->object->GetObjectParam()->GetStId()));
                    }
                }

                for (int j = 0; j < name_pos_list.size(); j++)
                {
                    if (ZERO == mViewObjectVector[i]->object->GetObjectParam()->GetObjectName().compare("StationView")&&
                       mViewObjectVector[i]->object->GetObjectParam()->GetX() == name_pos_list.at(j))
                    {
                        if (rundir == RUN_UP)
                        {
                            if (is_mirror)
                                mViewObjectVector[i]->object->GetObjectParam()->SetStId(tmp + count - j);
                            else
                                mViewObjectVector[i]->object->GetObjectParam()->SetStId(tmp + j + 1);
                        }
                        else if (rundir == RUN_DOWN)
                        {
                            if (is_mirror)
                                mViewObjectVector[i]->object->GetObjectParam()->SetStId(tmp -count + j);
                            else
                               mViewObjectVector[i]->object->GetObjectParam()->SetStId(tmp - j -1);
                        }
                        mViewObjectVector[i]->object->GetObjectParam()->SetName(QString("station%1").arg(mViewObjectVector[i]->object->GetObjectParam()->GetStId()));
                    }
                }

                for (int j = 0; j < line_pos_list.size(); j++)
                {
                    if (ZERO == mViewObjectVector[i]->object->GetObjectParam()->GetObjectName().compare("LineView")&&
                        mViewObjectVector[i]->object->GetObjectParam()->GetX() == line_pos_list.at(j))
                    {
                        if (rundir == RUN_UP)
                        {
                            if (is_mirror)
                                 mViewObjectVector[i]->object->GetObjectParam()->SetStId(tmp + count - j);
                            else
                                mViewObjectVector[i]->object->GetObjectParam()->SetStId(tmp + j + 2);
                        }
                        else if (rundir == RUN_DOWN)
                        {
                            if (is_mirror)
                                  mViewObjectVector[i]->object->GetObjectParam()->SetStId(tmp -count + j);
                            else
                                  mViewObjectVector[i]->object->GetObjectParam()->SetStId(tmp - j -2);
                        }
                    mViewObjectVector[i]->object->GetObjectParam()->SetName(QString("line%1").arg(mViewObjectVector[i]->object->GetObjectParam()->GetStId()));
                    }
                }
            }
        }
     }

    show_by_index(ptr);

    show();
}


//linux下使用这个抠图再使用clearmask不会闪屏
void DynamicMapShowWindow::paintEvent(QPaintEvent *event)
{
    event->ignore();

    if (m_setmask_flag)
    {
        //LOG_QDEBUG << "paintEvent setmask: " << m_sub_rect;
        QPainter p(this);
        p.setCompositionMode(QPainter::CompositionMode_Clear);
        p.fillRect(m_sub_rect, Qt::SolidPattern);
    }
}

void DynamicMapShowWindow::xml_to_vector(QString fullpath)
{
    LOG_QDEBUG << fullpath;
    QFile file(fullpath);
    if (!file.open(QFile::ReadOnly))
    {
        LOG_QDEBUG << "no file, file name:" << fullpath;
        return;
    }

    QDomDocument doc;
    QString err_msg;
    int err_line;
    int err_column;
    if (!doc.setContent(&file, false, &err_msg, &err_line, &err_column))
    {
        file.close();
        LOG_QDEBUG << "XML setContent fail,Msg:" << err_msg << " Line:" << err_line << " Column:" << err_column;
        return;
    }

    if (doc.isNull())
    {
        file.close();
        LOG_QDEBUG << "doc is null";
        return;
    }
    QDomElement body = doc.documentElement();

    if (body.hasAttribute("current"))
    {
        m_current_station_pos = body.attribute("current","0").toInt();
    }

    if (body.hasAttribute("interval_station_num"))
    {
        m_interval_station_num = body.attribute("interval_station_num", 0).toInt();
    }

    if (body.hasAttribute("all_station_num"))
    {
        m_all_station_num = body.attribute("all_station_num", 0).toInt();
    }

    if (body.hasAttribute("width"))
    {
        setFixedWidth(body.attribute("width", 0).toInt());
    }

    if (body.hasAttribute("height"))
    {
        setFixedHeight(body.attribute("height", 0).toInt());
    }

    if (body.hasAttribute("interval_offset"))
    {
        interval_unequal_offset = body.attribute("interval_offset", 0).toInt();
    }
    if (body.hasAttribute("all_offset"))
    {
        all_unequal_offset = body.attribute("all_offset", 0).toInt();
    }

    QDomElement ui = body.firstChildElement("ui");

    QDomNodeList itemList = ui.childNodes();

    if (itemList.isEmpty())
    {
        file.close();
        return;
    }

    for (int i = 0; i < itemList.count(); i++)
    {
        QDomElement item;
        item = itemList.item(i).toElement();
        if (item.isComment() || item.isNull())
            continue;

        QString type = item.attribute("type", "null");

        QString name = item.attribute("name", "null");
        if (name.contains("acrossxml"))
        {
            //新来的跨越xml控件都会存起来
            m_new_acrossxml_objs.push_back(name);

            if (m_shown_acrossxml_objs.contains(name))
                continue;
            else
                m_shown_acrossxml_objs.push_back(name);
        }

        QString filename = QFileInfo(file).fileName();

        //存储新来的控件方便后面重新显示
        m_new_objs.push_back(filename + name);

        //来过的控件就不再重新分配内存了
        if (m_shown_objs.contains(filename + name))
        {
            //只需要重新设置数据即可acrossxml控件需要重新加载因为可能已经被删除
            if (!name.contains("acrossxml"))
            {
                m_shown_objs[filename + name]->object->ParseXML(&item);
                m_shown_objs[filename + name]->object->GetObjectParam()->SetObjectName(type);
                continue;
            }
        }

        QString object_register_name = type + QString("*");
        int ret = QMetaType::type(object_register_name.toLatin1());
        if (ret == 0)
            return;
        ViewObjectInfo *info = new ViewObjectInfo;

        info->object = static_cast<ViewObject*>(QMetaType::metaObjectForType(ret)->newInstance());

        if (NULL != info->object)
        {
            mViewObjectVector.push_back(info);
            info->object->ParseXML(&item);
            info->object->GetObjectParam()->SetObjectName(type);

            m_shown_objs[filename + name] = info;
            info->unique_name = filename + name;
        }
        else
        {
            delete info;
        }
    }
    file.close();
}
